#include "graphsupport/graph/operation/AddChpExpWeightsOperation.h"

#include <ext/hash_set>

#include "graphsupport/graph/BiGraph.h"


AddChpExpWeightsOperation::AddChpExpWeightsOperation()
{
}

void AddChpExpWeightsOperation::applyTo( Graph & graph, IOperationSettings & genSettings )
{
	int n = graph.getVertexCount();
	int createCheapSrcEnd = n;
	int findCheapDestBeg = 0;
	Graph::AdjMatrixType adgMatr = graph.getAdjacentMatrixArr();

	BiGraph * bigraph = dynamic_cast< BiGraph * >( & graph );
	if ( bigraph != 0 )
	{
		createCheapSrcEnd = bigraph->getFirstBipart();
		findCheapDestBeg = bigraph->getFirstBipart();
	}

	std::vector< int > pair( n, -1 );
	std::vector< int > noPairNeighbors;
	std::vector< int > allNeighbors;

	for ( int i = 0; i < createCheapSrcEnd; i++ )
	{
		noPairNeighbors.clear();
		allNeighbors.clear();
		for ( int j = findCheapDestBeg; j < n; j++ )
		{
			if ( graph.existsEdge( i, j ) )
			{
				adgMatr[i][j] = genSettings.expensiveBeg + genSettings.randomDouble() * genSettings.expensiveRange;
				allNeighbors.push_back( j );
				if ( pair[j] == -1 )
				{
					noPairNeighbors.push_back( j );
				}
			}
		}

		std::vector< int > & candidates = noPairNeighbors.size() > 0 ? noPairNeighbors : allNeighbors;
		if ( candidates.size() == 0 )
		{
			continue;
		}
		assert( candidates.size() > 0 );

		int cheapPair = candidates[genSettings.randomInt( candidates.size() )];
		adgMatr[i][cheapPair] = genSettings.cheapBeg + genSettings.randomDouble() * genSettings.cheapRange;
		pair[i] = cheapPair;
		pair[cheapPair] = i;
	}

	if ( bigraph != 0 )
	{
		for ( int i = bigraph->getFirstBipart(); i < n; i++ )
		{
			for ( int j = 0; j < n; j++ )
			{
				graph.eraseEdge( i, j );
			}
		}
		for ( int i = 0; i < bigraph->getFirstBipart(); i++ )
		{
			for ( int j = 0; j < bigraph->getFirstBipart(); j++ )
			{
				graph.eraseEdge( i, j );
			}
		}
	}
}
